import { Ref, watchEffect } from "vue";
import { Point, line } from ".";
import { DrawingSurfaceHelper, clientPosCvt } from "..";

type DrawingCallee = (
  ctx: CanvasRenderingContext2D,
  startPos: Point,
  endPos: Point
) => void;
type FinishCallee = DrawingCallee;
type StartCallee = (ctx: CanvasRenderingContext2D, startPos: Point) => void;

export interface GuidewiresInfo {
  color?: string;
  type?: "StartPos" | "EndPos" | "StartEndPos";
}

export class DrawingAssist {
  static create(ctx: CanvasRenderingContext2D) {
    return new DrawingAssist(ctx);
  }
  // private ctx: CanvasRenderingContext2D;
  private _drawingCallee?: DrawingCallee;
  private _doDefaultStartOpt: boolean;
  private _startCallee?: StartCallee | null;
  private _finishCallee?: FinishCallee;
  private _guidewiresInfo?: GuidewiresInfo;
  private _startPos: null | Point;
  private _dsHelper: DrawingSurfaceHelper;

  constructor(ctx: CanvasRenderingContext2D) {
    // this.ctx = ctx;
    this._startPos = null;
    this._doDefaultStartOpt = true;
    this._dsHelper = DrawingSurfaceHelper.create(ctx);
    const { width: canvasW, height: canvasH } = ctx.canvas;
    ctx.canvas.onmousedown = (e) => {
      this._startPos = clientPosCvt(ctx, e);
      this._startCallee?.(ctx, this._startPos);
      if (this._doDefaultStartOpt) {
        this._dsHelper.takeSnapshot();
      }
    };
    ctx.canvas.onmousemove = (e) => {
      if (!this._startPos) return;
      this._dsHelper.restoreSnapshot();
      const endPos = clientPosCvt(ctx, e);
      // 绘制目标图形
      this._drawingCallee?.(ctx, this._startPos, endPos);
      // 绘制 guidewires
      if (this._guidewiresInfo) {
        const { color } = this._guidewiresInfo;
        const drawGuidewires = ({ x, y }: Point) => {
          line.draw(ctx, {
            x1: 0,
            y1: y,
            x2: canvasW,
            y2: y,
            strokeStyle: color,
          });
          line.draw(ctx, {
            x1: x,
            y1: 0,
            x2: x,
            y2: canvasH,
            strokeStyle: color,
          });
        };
        const { type: wiresType } = this._guidewiresInfo;
        if (wiresType === "EndPos" || wiresType === "StartEndPos") {
          drawGuidewires(endPos);
        }
        if (wiresType === "StartPos" || wiresType === "StartEndPos") {
          drawGuidewires(this._startPos);
        }
      }
    };
    ctx.canvas.onmouseup = (e) => {
      if (!this._startPos) return;
      this._dsHelper.restoreSnapshot();
      const endPos = clientPosCvt(ctx, e);
      this._drawingCallee?.(ctx, this._startPos, endPos);
      this._finishCallee?.(ctx, this._startPos, endPos);
      this._startPos = null;
    };
  }
  takeSnapshot() {
    this._dsHelper.takeSnapshot();
  }

  setStartCallee(
    startCallee: StartCallee | null,
    doDefaultStartOpt: boolean = true
  ) {
    this._startCallee = startCallee;
    this._doDefaultStartOpt = doDefaultStartOpt;
    return this;
  }

  setFinishCallee(finishCallee: FinishCallee) {
    this._finishCallee = finishCallee;
    return this;
  }

  setDrawingCallee(drawingCallee: DrawingCallee) {
    this._drawingCallee = drawingCallee;
    return this;
  }

  useGuidewires(guidewiresInfo: GuidewiresInfo = {}) {
    this._guidewiresInfo = { ...guidewiresInfo };
    if (!this._guidewiresInfo.color) {
      this._guidewiresInfo.color = "blue";
    }
    if (!this._guidewiresInfo.type) {
      this._guidewiresInfo.type = "EndPos";
    }
    return this;
  }

  disuseGuidewires() {
    this._guidewiresInfo = undefined;
    return this;
  }

  setGuidewiresRef(ref: Ref<boolean>) {
    watchEffect(() => {
      if (ref.value) {
        this.useGuidewires();
      } else {
        this.disuseGuidewires();
      }
    });
    return this;
  }
}
